package service

import (
	"context"
	"encoding/json"
	"k8s-dash/utils"
	appsV1 "k8s.io/api/apps/v1"
	metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"strconv"
	"time"
)

type statefulset struct{}

var Statefulset statefulset

type StsResp struct {
	Total int                  `json:"total"`
	Items []appsV1.StatefulSet `json:"items"`
}
type StsToNS struct {
	Namespace string `json:"namespaces"`
	StsNum    int    `json:"sts_num"`
}

// GetStsList 获取deploy列表
func (p *statefulset) GetStsList(filterName, namespace string, limit, page int) (resp *StsResp, err error) {
	stsList, err := utils.K8sClient.K8sClient.AppsV1().StatefulSets(namespace).List(context.TODO(), metaV1.ListOptions{})
	if err != nil {
		return nil, err
	}
	//清洗数据
	selectedData := &dataSelector{
		GenericDataList: p.toCells(stsList.Items),
		DataSelectQuery: &DataSelectorQuery{
			Filter:   &FilterQuery{filterName},
			Paginate: &PageQuery{limit, page},
		},
	}
	//先过滤
	sd := selectedData.Filter()
	total := len(sd.GenericDataList)
	//排序
	data := sd.Sort().Paginate()
	//再将数据装换为appsV1.Deployment
	ds := p.FromCells(data.GenericDataList)
	//返回数据
	return &StsResp{
		Total: total,
		Items: ds,
	}, nil
}

// GetStsDetail 获取deploy详情
func (p *statefulset) GetStsDetail(name, namespace string) (*appsV1.StatefulSet, error) {
	sts, err := utils.K8sClient.K8sClient.AppsV1().StatefulSets(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
	if err != nil {
		return nil, err
	}
	return sts, nil
}

// RestartSts 触发重启机制
func (p *statefulset) RestartSts(name, namespace string) error {
	//随便改一个值就会触发重启
	patchData := map[string]interface{}{
		"spec": map[string]interface{}{
			"template": map[string]interface{}{
				"spec": map[string]interface{}{
					"containers": []map[string]interface{}{
						{
							"name": name,
							"env": []map[string]interface{}{
								{
									"name":  "RESTART_",
									"value": strconv.FormatInt(time.Now().Unix(), 10),
								},
							},
						},
					},
				},
			},
		},
	}
	//序列化
	bytes, err := json.Marshal(patchData)
	if err != nil {
		return err
	}
	//调用sdk更新
	if _, err := utils.K8sClient.K8sClient.AppsV1().StatefulSets(namespace).Patch(context.TODO(), name, "application/strategic-merge-patch+json", bytes, metaV1.PatchOptions{}); err != nil {
		return err
	}
	return nil
}

// ScaleSts 扩缩容副本
func (p *statefulset) ScaleSts(name, namespace string, scaleNum int) (int32, error) {
	scale, err := utils.K8sClient.K8sClient.AppsV1().StatefulSets(namespace).GetScale(context.TODO(), name, metaV1.GetOptions{})
	if err != nil {
		return 0, err
	}
	scale.Spec.Replicas = int32(scaleNum)
	updateScale, err := utils.K8sClient.K8sClient.AppsV1().StatefulSets(namespace).UpdateScale(context.TODO(), name, scale, metaV1.UpdateOptions{})
	if err != nil {
		return 0, err
	}
	return updateScale.Status.Replicas, nil
}

// DeleteSts 删除sts
func (p *statefulset) DeleteSts(name, namespace string) error {
	return utils.K8sClient.K8sClient.AppsV1().StatefulSets(namespace).Delete(context.TODO(), name, metaV1.DeleteOptions{})
}

// UpdateSts 更新pod
func (p *statefulset) UpdateSts(namespace, content string) error {
	var deploy = &appsV1.StatefulSet{}
	//将content反序列化为pod
	err := json.Unmarshal([]byte(content), deploy)
	if err != nil {
		return err
	}
	if _, err := utils.K8sClient.K8sClient.AppsV1().StatefulSets(namespace).Update(context.TODO(), deploy, metaV1.UpdateOptions{}); err != nil {
		return err
	}
	return nil
}

// GetStsToNS 获取对应namespace下deploy的数量，这个功能跟podList功能重复，这个是获取所有ns分别对应的pod数量
func (p *statefulset) GetStsToNS() (DENS []*StsToNS, err error) {
	//首先获取所有的ns
	namespaceList, err := utils.K8sClient.K8sClient.CoreV1().Namespaces().List(context.TODO(), metaV1.ListOptions{})
	if err != nil {
		return nil, err
	}
	for _, namespace := range namespaceList.Items {
		deployList, err := utils.K8sClient.K8sClient.AppsV1().StatefulSets(namespace.Name).List(context.TODO(), metaV1.ListOptions{})
		if err != nil {
			return nil, err
		}
		//组装数据
		dns := &StsToNS{
			Namespace: namespace.Name,
			StsNum:    len(deployList.Items),
		}
		DENS = append(DENS, dns)
	}
	return DENS, nil
}

// 类型转换的方法 coreV1.pod => DataCell,DataCell => coreV1.pod
func (p *statefulset) toCells(ds []appsV1.StatefulSet) []DataCell {
	cells := make([]DataCell, len(ds))
	for i := range ds {
		cells[i] = stsCell(ds[i])
	}
	return cells
}

func (p *statefulset) FromCells(cells []DataCell) []appsV1.StatefulSet {
	ds := make([]appsV1.StatefulSet, len(cells))
	for i := range cells {
		ds[i] = appsV1.StatefulSet(cells[i].(stsCell))
	}
	return ds
}
